# 使用C扩展
# CPython还为开发者实现了一个有趣的特性，使用Python可以轻松调用C代码
# 开发者有三种方法可以在自己的Python代码中来调用C编写的函数-ctypes，SWIG，Python/C API。每种方式也都有各自的利弊。
# 首先，我们要明确为什么要在Python中调用C？
# 常见原因如下： - 你要提升代码的运行速度，而且你知道C要比Python快50倍以上 - C语言中有很多传统类库，而且有些正是你想要的，
# 但你又不想用Python去重写它们 - 想对从内存到文件接口这样的底层资源进行访问 - 不需要理由，就是想这样做


# 1 ctypes
# 实现两数求和的C代码，保存为add.c

# //sample C file to add 2 numbers - int and floats

#include <stdio.h>
# int add_int(int, int);
# float add_float(float, float);
#
# int add_int(int num1, int num2){
#     return num1 + num2;
#
# }
#
# float add_float(float num1, float num2){
#     return num1 + num2;
#
# }


# 接下来将C文件编译为.so文件(windows下为DLL)。下面操作会生成adder.so文件
#For Linux
# $  gcc -shared -Wl,-soname,adder -o adder.so -fPIC adder.c
#For Mac
# $ gcc -shared -Wl,-install_name,adder.so -o adder.so -fPIC adder.c

# 现在在你的Python代码中来调用它

from ctypes import *

#load the shared object file
adder = CDLL('./adder.so')

#Find sum of integers
res_int = adder.add_int(4,5)
print("Sum of 4 and 5 = " + str(res_int))

#Find sum of floats
a = c_float(5.5)
b = c_float(4.1)

add_float = adder.add_float
add_float.restype = c_float
print("Sum of 5.5 and 4.1 = ", str(add_float(a, b)))

# 输出如下
# Sum of 4 and 5 = 9
# Sum of 5.5 and 4.1 =  9.60000038147

# 当adder.add_int()被调用时，内部将发起一个对C函数add_int的调用。ctypes接口允许我们在调用C函数时使用原生Python中默认的字符串型和整型。
# 而对于其他类似布尔型和浮点型这样的类型，必须要使用正确的ctype类型才可以。如向adder.add_float()函数传参时,
# 我们要先将Python中的十进制值转化为c_float类型，然后才能传送给C函数。这种方法虽然简单，清晰，但是却很受限。例如，并不能在C中对对象进行操作


# 2. SWIG
# SWIG是Simplified Wrapper and Interface Generator的缩写。是Python中调用C代码的另一种方法。在这个方法中，
# 开发人员必须编写一个额外的接口文件来作为SWIG(终端工具)的入口
# python开发者一般不会采用这种方法，因为大多数情况它会带来不必要的复杂。而当你有一个C/C++代码库需要被多种语言调用时，这将是个非常不错的选择


# 3. python/C API
